package org.iplatform.felicajack.mfcaccess;

import java.util.Map;
import java.util.WeakHashMap;

import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;

import com.felicanetworks.mfc.AppInfo;
import com.felicanetworks.mfc.Felica;
import com.felicanetworks.mfc.FelicaEventListener;
import com.felicanetworks.mfc.FelicaException;
import com.felicanetworks.mfc.PushIntentSegment;
import com.felicanetworks.mfc.PushStartBrowserSegment;
import com.felicanetworks.mfc.PushStartMailerSegment;

/**
 * MFCの利用方法のサンプルを示すクラス
 *
 */
public class MFCSampleUse implements FelicaEventListener {

    private static final String TAG = "MFCSampleUse";

    /**
     * 許可証配列。必要に応じて適切な値を設定。 (サンプルアプリケーションではnullとしている)
     */
    private static final String[] PERMITS = null;

    /**
     * ブラウザ起動URL(Push送信(ブラウザ起動)パラメータ)
     */
    private static final String BROWSER_URL = "http://www.felicanetworks.co.jp/";

    /**
     * Toアドレス(Push送信(メーラ起動)パラメータ)
     */
    private static final String[] TO_ADDRESSES = { "foo@bar.hoge" };

    /**
     * CCアドレス(Push送信(メーラ起動)パラメータ)
     */
    private static final String[] CC_ADDRESSES = { "bar@hoge.foo" };

    /**
     * Subject(push送信(メーラ起動)パラメータ)
     */
    private static final String MAIL_SUBJECT = "Push Test";

    /**
     * Body(push送信(メーラ起動)パラメータ)
     */
    private static final String MAIL_BODY = "How about the push test?";

    /**
     * Felicaインスタンス
     */
    private Felica felica = null;

    /**
     * Viewインスタンス
     */
//    private View view = null;
    private Context context = null;

    // シングルトンにする
    private static MFCSampleUse instance = new MFCSampleUse();

    private MFCSampleUse() {

    }

    public static MFCSampleUse getInstance() {

        return instance;
    }

    public void setFelica(final Felica felica) {

        this.felica = felica;
    }

//    public void setView(final View view) {
//
//        this.view = view;
//    }

    public void setContext(final Context context) {
    	this.context = context;
    }

    /*
     * 共通処理のサンプルコード
     */

    /**
     * Felicaの利用開始処理を実行します。
     */
    public void activateFelica(final FelicaEventListener listner) {

        // まず前処理の情報をクリア
        clear();

        // 状態チェック
        try {
            checkFelica();

        } catch (final IllegalArgumentException e) {
            requestToDisplay("Felica#activateFelica() failed." + e.getMessage());
            return;
        }

        try {
            // FeliCaチップの利用開始処理
            // 第1引数には、フェリカネットワークスより払い出された許可証
            // (複数ある場合は許可証配列)を、第2引数には、
            // 利用開始処理結果通知用リスナFelicaEventListenerを指定。
            felica.activateFelica(PERMITS, listner);
            requestToDisplay("Felica#activateFelica() succeeded. waiting...");
        } catch (final IllegalArgumentException e) {
            // 不正な引数が指定された場合
            requestToDisplay(e.getMessage());
        } catch (final FelicaException e) {
            // FelicaExceptionをキャッチした場合
            handleFelicaException(e);
        } catch (final Exception e) {
            // 予期せぬ例外をキャッチした場合
            handleUnexpectedException(e);
        }
    }

    /**
     * Felicaの利用終了処理を実行します。
     */
    public void inactivateFelica() {

        // 前処理の情報をクリア
        clear();

        // 状態チェック
        try {
            checkFelica();

        } catch (final IllegalArgumentException e) {
            requestToDisplay("Felica#inactivateFelica() failed" + e.getMessage());
            return;
        }

        try {
            // FeliCaチップの利用終了処理
            // (Felica#activateFelica()の処理結果待ちの場合、利用開始処理をキャンセルする)
            felica.inactivateFelica();
            requestToDisplay("Felica#inactivateFelica() succeeded!");
        } catch (final FelicaException e) {
            // FelicaExceptionをキャッチした場合
            handleFelicaException(e);
        } catch (final Exception e) {
            // 予期せぬ例外をキャッチした場合
            handleUnexpectedException(e);
        }
    }

    /**
     * Felicaチップをオープンします。
     */
    public void open() {

        // 前処理の情報をクリア
        clear();

        // 状態チェック
        try {
            checkFelica();

        } catch (final IllegalArgumentException e) {
            requestToDisplay("Felica#open() failed." + e.getMessage());
            return;
        }

        try {
            // FeliCaチップのオープン
            felica.open();
            requestToDisplay("Felica#open() succeeded!");
        } catch (final FelicaException e) {
            // FelicaExceptionをキャッチした場合
            handleFelicaException(e);
        } catch (final Exception e) {
            // 予期せぬ例外をキャッチした場合
            handleUnexpectedException(e);
        }
    }

    /**
     * Felicaチップをクローズします。
     */
    public void close() {

        // 前処理の情報をクリア
        clear();

        // 状態チェック
        try {
            checkFelica();

        } catch (final IllegalArgumentException e) {
            requestToDisplay("Felica#close() failed." + e.getMessage());
            return;
        }

        try {
            // FeliCaチップのクローズ
            felica.close();
            requestToDisplay("Felica#close() succeeded!");
        } catch (final FelicaException e) {
            // FelicaExceptionをキャッチした場合
            handleFelicaException(e);
        } catch (final Exception e) {
            // 予期せぬ例外をキャッチした場合
            handleUnexpectedException(e);
        }
    }

    /*
     * Push送信のサンプルコード
     */

    /**
     * Push送信によって、ブラウザを起動します。
     */
    public void pushToStartBrowser() {

        // 前処理の情報をクリア
        clear();

        // 状態チェック
        try {
            checkFelica();

        } catch (final IllegalArgumentException e) {
            requestToDisplay("Felica#push() (start browser) failed." + e.getMessage());
            return;
        }

        try {
            // ブラウザ起動パラメータの生成
            final PushStartBrowserSegment pushSegment = new PushStartBrowserSegment(BROWSER_URL, null);

            // Push送信
            felica.push(pushSegment);

            requestToDisplay("Felica#push() (start browser) succeeded!");
        } catch (final IllegalArgumentException e) {
            // // 不正な引数が指定された場合
            requestToDisplay(e.getMessage());
        } catch (final FelicaException e) {
            // FelicaExceptionをキャッチした場合
            handleFelicaException(e);
        } catch (final Exception e) {
            // 予期せぬ例外をキャッチした場合
            handleUnexpectedException(e);
        }
    }

    /**
     * Push送信によって、メーラを起動します。
     */
    public void pushToStartMailer() {

        // 前処理の情報をクリア
        clear();

        // 状態チェック
        try {
            checkFelica();

        } catch (final IllegalArgumentException e) {
            requestToDisplay("Felica#push() (start mailer) failed." + e.getMessage());
            return;
        }

        try {
            // メーラ起動パラメータの生成
            final PushStartMailerSegment pushSegment = new PushStartMailerSegment(TO_ADDRESSES,
                    CC_ADDRESSES, MAIL_SUBJECT, MAIL_BODY, null);

            // Push送信
            felica.push(pushSegment);

            requestToDisplay("Felica#push() (start mailer) succeeded!");
        } catch (final IllegalArgumentException e) {
            // 不正な引数が指定された場合
            requestToDisplay(e.getMessage());
        } catch (final FelicaException e) {
            // FelicaExceptionをキャッチした場合
            handleFelicaException(e);
        } catch (final Exception e) {
            // 予期せぬ例外をキャッチした場合
            handleUnexpectedException(e);
        }
    }

    /*
     * Android依存コード(ここから)
     */

    /**
     * Androidインテント実行対象コンポーネント名
     */
//    private static final ComponentName INTENT_TARGET_COMPONENT_NAME = new ComponentName(
//            "com.felicanetworks.mfcsample.ui.android",
//            "com.felicanetworks.mfcsample.ui.android.CommonOperationActivity");
    private static final ComponentName INTENT_ADD_USER_COMPONENT_NAME = new ComponentName(
            "org.iplatform.felicajack",
            "org.iplatform.felicajack.HUserAddActivity");

    public boolean pushToAddUserIntent(final String userName) {
        // 前処理の情報をクリア
        clear();

        // 状態チェック
        try {
            checkFelica();

        } catch (final IllegalArgumentException e) {
            requestToDisplay("Felica#push() (send Intent) failed." + e.getMessage());
            return false;
        }

        try {
            // Androidインテント実行パラメータの生成
            PushIntentSegment pushSegment;
            final Intent intent = new Intent();
            intent.setComponent(INTENT_ADD_USER_COMPONENT_NAME);
            intent.putExtra("UserName", userName);
            pushSegment = new PushIntentSegment(intent);

            // Push送信
            felica.push(pushSegment);

            requestToDisplay("Felica#push() (send Intent) succeeded!");
            return true;
        } catch (final IllegalArgumentException e) {
        	e.printStackTrace();
            // 不正な引数が指定された場合
            requestToDisplay(e.getMessage());
        } catch (final FelicaException e) {
        	e.printStackTrace();
            // FelicaExceptionをキャッチした場合
            handleFelicaException(e);
        } catch (final Exception e) {
        	e.printStackTrace();
            // 予期せぬ例外をキャッチした場合
            handleUnexpectedException(e);
        }
        return false;
    }

    private static final ComponentName INTENT_DRAW_CARD_COMPONENT_NAME = new ComponentName(
            "org.iplatform.felicajack",
            "org.iplatform.felicajack.HUserAddActivity");

    public boolean pushToDrawCardIntent(final int kind, final int number) {
        // 前処理の情報をクリア
        clear();

        // 状態チェック
        try {
            checkFelica();

        } catch (final IllegalArgumentException e) {
            requestToDisplay("Felica#push() (send Intent) failed." + e.getMessage());
            return false;
        }

        try {
            // Androidインテント実行パラメータの生成
            PushIntentSegment pushSegment;
            final Intent intent = new Intent();
            intent.setComponent(INTENT_DRAW_CARD_COMPONENT_NAME);
            intent.putExtra("kind", kind);
            intent.putExtra("number", number);
            pushSegment = new PushIntentSegment(intent);

            // Push送信
            felica.push(pushSegment);

            requestToDisplay("Felica#push() (send Intent) succeeded!");
            return true;
        } catch (final IllegalArgumentException e) {
        	e.printStackTrace();
            // 不正な引数が指定された場合
            requestToDisplay(e.getMessage());
        } catch (final FelicaException e) {
        	e.printStackTrace();
            // FelicaExceptionをキャッチした場合
            handleFelicaException(e);
        } catch (final Exception e) {
        	e.printStackTrace();
            // 予期せぬ例外をキャッチした場合
            handleUnexpectedException(e);
        }
        return false;
    }

    /**
     * Push送信によって、Androidインテントを送信します。
     */
    public void pushToSendIntent() {

        // 前処理の情報をクリア
        clear();

        // 状態チェック
        try {
            checkFelica();

        } catch (final IllegalArgumentException e) {
            requestToDisplay("Felica#push() (send Intent) failed." + e.getMessage());
            return;
        }

        try {
            // Androidインテント実行パラメータの生成
            PushIntentSegment pushSegment;
            final Intent intent = new Intent();
            intent.setComponent(INTENT_ADD_USER_COMPONENT_NAME);
            pushSegment = new PushIntentSegment(intent);

            // Push送信
            felica.push(pushSegment);

            requestToDisplay("Felica#push() (send Intent) succeeded!");
        } catch (final IllegalArgumentException e) {
            // 不正な引数が指定された場合
            requestToDisplay(e.getMessage());
        } catch (final FelicaException e) {
            // FelicaExceptionをキャッチした場合
            handleFelicaException(e);
        } catch (final Exception e) {
            // 予期せぬ例外をキャッチした場合
            handleUnexpectedException(e);
        }
    }

    /*
     * Android依存コード(ここまで)
     */

    /*
     * オフライン処理のサンプルコード
     */

    /**
     * RFSの状態を取得します。
     */
    public void getRFSState() {

        // 前処理の情報をクリア
        clear();

        // 状態チェック
        try {
            checkFelica();

        } catch (final IllegalArgumentException e) {
            requestToDisplay("Felica#getRFSState() failed." + e.getMessage());
            return;
        }

        try {

            // 搬送波の受信状況の取得
            final boolean state = felica.getRFSState();

            requestToDisplay("Felica#getRFSState() result:" + state);

        } catch (final FelicaException e) {
            // FelicaExceptionをキャッチした場合
            handleFelicaException(e);
        } catch (final Exception e) {
            // 予期せぬ例外をキャッチした場合
            handleUnexpectedException(e);
        }
    }

    /*
     * Felica#activateFelica()}の処理結果通知リスナの実装
     */

    @Override
    public void errorOccurred(final int id, final String msg, final AppInfo otherAppInfo) {

        String result = "Felica#activateFelica() failed\nError:";

        switch (id) {
        case FelicaEventListener.TYPE_USED_BY_OTHER_APP:
            // 他アプリケーションによってFeliCaチップが使用中の場合
            result += "FeliCa Chip is used by other application(PID:" + otherAppInfo.getPid() + ")";
            break;
        case FelicaEventListener.TYPE_NOT_FOUND_ERROR:
            // 利用可能な許可証がみつからなかった場合
            result += "valid permits not found";
            break;
        case FelicaEventListener.TYPE_HTTP_ERROR:
            // 許可証検証中にHTTPエラーが発生した場合
            result += "HTTP error";
            break;
        case FelicaEventListener.TYPE_MFC_VERSION_ERROR:
            // MFCのバージョンアップが必要な場合
            result += "MFC version is too old";
            break;
        case FelicaEventListener.TYPE_UTILITY_VERSION_ERROR:
            // MFCユーティリティのバージョンアップが必要な場合
            result += "MFC utility version is too old";
            break;
        case FelicaEventListener.TYPE_UNKNOWN_ERROR:
            // その他のエラー
            result += "unknown error";
            break;
        default:
            // MFC仕様上、想定外のパス
            result += "nexpected error";
            break;
        }
        if (msg != null) {
            result += "\nerror detail:" + msg;
        }
        requestToDisplay(result);
    }

    @Override
    public void finished() {

        requestToDisplay("Felica#activateFelica() succeeded!");
    }

    /*
     * 以降はprivateメソッド
     */

    /**
     * Felicaが設定されていることをチェックします
     */
    private void checkFelica() throws IllegalArgumentException {

        if (felica == null) {
            throw new IllegalArgumentException("Felica is not set");
        }
    }

    /**
     * FelicaExceptionの種別を文字列に変換するためのマップ。
     */
    private static final Map<Integer, String> FELICA_EXCEPTION_ID_CONVERSION_MAP = new WeakHashMap<Integer, String>() {

        {
            put(FelicaException.ID_UNKNOWN_ERROR, "ID_UNKNOWN_ERROR");
            put(FelicaException.ID_ILLEGAL_STATE_ERROR, "ID_ILLEGAL_STATE_ERROR");
            put(FelicaException.ID_IO_ERROR, "ID_IO_ERROR");
            put(FelicaException.ID_GET_KEY_VERSION_ERROR, "ID_GET_KEY_VERSION_ERROR");
            put(FelicaException.ID_READ_ERROR, "ID_READ_ERROR");
            put(FelicaException.ID_WRITE_ERROR, "ID_WRITE_ERROR");
            put(FelicaException.ID_SET_NODECODESIZE_ERROR, "ID_SET_NODECODESIZE_ERROR");
            put(FelicaException.ID_OPEN_ERROR, "ID_OPEN_ERROR");
            put(FelicaException.ID_GET_NODE_INFORMATION_ERROR, "ID_GET_NODE_INFORMATION_ERROR");
            put(FelicaException.ID_GET_PRIVACY_NODE_INFORMATION_ERROR,
                    "ID_GET_PRIVACY_NODE_INFORMATION_ERROR");
            put(FelicaException.ID_SET_PRIVACY_ERROR, "ID_SET_PRIVACY_ERROR");
            put(FelicaException.ID_PERMISSION_ERROR, "ID_PERMISSION_ERROR");
            put(FelicaException.ID_GET_BLOCK_COUNT_INFORMATION_ERROR,
                    "ID_GET_BLOCK_COUNT_INFORMATION_ERROR");
        }
    };

    /**
     * FelicaExceptionのタイプを文字列に変換するためのマップ。
     */
    private static final Map<Integer, String> FELICA_EXCEPTION_TYPE_CONVERSION_MAP = new WeakHashMap<Integer, String>() {

        {
            put(FelicaException.TYPE_NOT_OPENED, "TYPE_NOT_OPENED");
            put(FelicaException.TYPE_CURRENTLY_ONLINE, "TYPE_CURRENTLY_ONLINE");
            put(FelicaException.TYPE_NOT_SELECTED, "TYPE_NOT_SELECTED");
            put(FelicaException.TYPE_NOT_ACTIVATED, "TYPE_NOT_ACTIVATED");
            put(FelicaException.TYPE_INVALID_RESPONSE, "TYPE_INVALID_RESPONSE");
            put(FelicaException.TYPE_TIMEOUT_OCCURRED, "TYPE_TIMEOUT_OCCURRED");
            put(FelicaException.TYPE_OPEN_FAILED, "TYPE_OPEN_FAILED");
            put(FelicaException.TYPE_SELECT_FAILED, "TYPE_SELECT_FAILED");
            put(FelicaException.TYPE_GET_KEY_VERSION_FAILED, "TYPE_GET_KEY_VERSION_FAILED");
            put(FelicaException.TYPE_SERVICE_NOT_FOUND, "TYPE_SERVICE_NOT_FOUND");
            put(FelicaException.TYPE_BLOCK_NOT_FOUND, "TYPE_BLOCK_NOT_FOUND");
            put(FelicaException.TYPE_PIN_NOT_CHECKED, "TYPE_PIN_NOT_CHECKED");
            put(FelicaException.TYPE_READ_FAILED, "TYPE_READ_FAILED");
            put(FelicaException.TYPE_PURSE_FAILED, "TYPE_PURSE_FAILED");
            put(FelicaException.TYPE_CASH_BACK_FAILED, "TYPE_CASH_BACK_FAILED");
            put(FelicaException.TYPE_INVALID_PIN, "TYPE_INVALID_PIN");
            put(FelicaException.TYPE_CHECK_PIN_LIMIT, "TYPE_CHECK_PIN_LIMIT");
            put(FelicaException.TYPE_CHECK_PIN_OVERRUN, "TYPE_CHECK_PIN_OVERRUN");
            put(FelicaException.TYPE_WRITE_FAILED, "TYPE_WRITE_FAILED");
            put(FelicaException.TYPE_ENABLE_PIN_FAILED, "TYPE_ENABLE_PIN_FAILED");
            put(FelicaException.TYPE_FELICA_NOT_SET, "TYPE_FELICA_NOT_SET");
            put(FelicaException.TYPE_DEVICELIST_NOT_SET, "TYPE_DEVICELIST_NOT_SET");
            put(FelicaException.TYPE_LISTENER_NOT_SET, "TYPE_LISTENER_NOT_SET");
            put(FelicaException.TYPE_COMMUNICATION_START_FAILED, "TYPE_COMMUNICATION_START_FAILED");
            put(FelicaException.TYPE_SET_NODECODESIZE_FAILED, "TYPE_SET_NODECODESIZE_FAILED");
            put(FelicaException.TYPE_GET_CONTAINER_ISSUE_INFORMATION_FAILED,
                    "TYPE_GET_CONTAINER_ISSUE_INFORMATION_FAILED");
            put(FelicaException.TYPE_NOT_IC_CHIP_FORMATTING, "TYPE_NOT_IC_CHIP_FORMATTING");
            put(FelicaException.TYPE_ILLEGAL_NODECODE, "TYPE_ILLEGAL_NODECODE");
            put(FelicaException.TYPE_GET_NODE_INFORMATION_FAILED,
                    "TYPE_GET_NODE_INFORMATION_FAILED");
            put(FelicaException.TYPE_GET_PRIVACY_NODE_INFORMATION_FAILED,
                    "TYPE_GET_PRIVACY_NODE_INFORMATION_FAILED");
            put(FelicaException.TYPE_SET_PRIVACY_FAILED, "TYPE_SET_PRIVACY_FAILED");
            put(FelicaException.TYPE_NOT_CLOSED, "TYPE_NOT_CLOSED");
            put(FelicaException.TYPE_ILLEGAL_METHOD_CALL, "TYPE_ILLEGAL_METHOD_CALL");
            put(FelicaException.TYPE_PUSH_FAILED, "TYPE_PUSH_FAILED");
            put(FelicaException.TYPE_ALREADY_ACTIVATED, "TYPE_ALREADY_ACTIVATED");
            put(FelicaException.TYPE_GET_BLOCK_COUNT_INFORMATION_FAILED,
                    "TYPE_GET_BLOCK_COUNT_INFORMATION_FAILED");
            put(FelicaException.TYPE_RESET_FAILED, "TYPE_RESET_FAILED");
            put(FelicaException.TYPE_GET_SYSTEM_CODE_LIST_FAILED,
                    "TYPE_GET_SYSTEM_CODE_LIST_FAILED");
            put(FelicaException.TYPE_GET_CONTAINER_ID_FAILED, "TYPE_GET_CONTAINER_ID_FAILED");
            put(FelicaException.TYPE_REMOTE_ACCESS_FAILED, "TYPE_REMOTE_ACCESS_FAILED");
            put(FelicaException.TYPE_CURRENTLY_ACTIVATING, "TYPE_CURRENTLY_ACTIVATING");
            put(FelicaException.TYPE_ILLEGAL_SYSTEMCODE, "TYPE_ILLEGAL_SYSTEMCODE");
            put(FelicaException.TYPE_GET_RFS_STATE_FAILED, "TYPE_GET_RFS_STATE_FAILED");
            put(FelicaException.TYPE_INVALID_SELECTED_INTERFACE, "TYPE_INVALID_SELECTED_INTERFACE");
            put(FelicaException.TYPE_FELICA_NOT_AVAILABLE, "TYPE_FELICA_NOT_AVAILABLE");
        }
    };

    /**
     * FelicaExceptionの内容に応じて、エラー処理を実施します。 処理の内容は以下の通り。
     * ・ID_UNKNOWN_ERRORが発生した場合に、FeliCaチップのクローズ、およびFeliCaチップの利用終了処理を実施
     * ・(ID_OPEN_ERROR, TYPE_NOT_IC_CHIP_FORMATTING)が発生した場合に、FeliCaチップの利用終了処理を実施
     * ・エラー内容を画面に表示
     *
     * @param e 処理対象のFelicaException
     */
    private void handleFelicaException(final FelicaException e) {

        String errMsg;
        final String iDString = FELICA_EXCEPTION_ID_CONVERSION_MAP.get(e.getID());
        final String typeString = FELICA_EXCEPTION_TYPE_CONVERSION_MAP.get(e.getType());
        String additionalMsg = null;

        switch (e.getID()) {
        case FelicaException.ID_UNKNOWN_ERROR:
            // 未知のエラーが発生
            // 復帰不能なのでFelica#close()、#inactivateFelica()を実行
            try {
                felica.close();
                felica.inactivateFelica();
            } catch (final FelicaException e1) {
                // 強制終了処理に失敗した場合、キャッチした例外を無視
            }
            break;
        case FelicaException.ID_OPEN_ERROR:
            if (e.getType() == FelicaException.TYPE_NOT_IC_CHIP_FORMATTING) {
                // Felica#inactivateFelica()を実行し、FeliCaチップの利用終了処理を実施
                try {
                    felica.inactivateFelica();
                } catch (final FelicaException e1) {
                    // 利用終了処理に失敗した場合、キャッチした例外を無視
                }
            }
            break;
        default:
            break;
        }

        // エラー内容をViewに表示

        // ベースメッセージ生成
        errMsg = "caught FelicaException\n(ID, TYPE)=(" + iDString + ", " + typeString + ")";

        // 追加メッセージ作成
        switch (e.getID()) {
        case FelicaException.ID_UNKNOWN_ERROR:
            // 復帰困難なエラーが発生した旨を表示
            additionalMsg = "(Non-recoverable error)";
            break;
        case FelicaException.ID_READ_ERROR:
        case FelicaException.ID_WRITE_ERROR:
        case FelicaException.ID_GET_NODE_INFORMATION_ERROR:
        case FelicaException.ID_GET_PRIVACY_NODE_INFORMATION_ERROR:
        case FelicaException.ID_GET_BLOCK_COUNT_INFORMATION_ERROR:
        case FelicaException.ID_SET_PRIVACY_ERROR:
            // ステータスフラグ取得
            additionalMsg = "Status Flag1:" + e.getStatusFlag1() + ", StatusFlag2:"
                    + e.getStatusFlag2();
            break;
        default:
            break;
        }

        if (additionalMsg != null) {
            errMsg += "\n";
            errMsg += additionalMsg;
        }
        requestToDisplay(errMsg);
    }

    /**
     * 予期しないエラーへの処理を実施します(予期しないエラーか否かは呼出元で判定済)。 処理の内容は以下の通り。
     * ・FeliCaチップのクローズ、およびFeliCaチップの利用終了処理を実施 ・エラー内容を画面に表示
     *
     * @param e 処理対象のException
     */
    private void handleUnexpectedException(final Exception e) {

        // 復帰不能なのでFelica#close()、#inactivateFelica()を実行
        try {
            felica.close();
            felica.inactivateFelica();
        } catch (final FelicaException e1) {
            // 強制終了処理に失敗した場合、キャッチした例外を無視
        }

        // エラー内容をViewに表示
        requestToDisplay(e.getMessage());
    }

    static final Handler handler = new Handler();
    /**
     * Viewへ表示を要求します。何らかの理由でViewへの表示要求に失敗する場合、LogCatへ出力します。
     * @param content 表示内容
     */
    private void requestToDisplay(final String content) {
        try {
//            view.requestToDisplay(content);
        	handler.post(new Runnable() {

				@Override
				public void run() {
					// TODO Auto-generated method stub
					Toast.makeText(context, content, Toast.LENGTH_LONG).show();
				}
			});

        } catch (final Exception e) {
            Log.d(TAG, "requestToDisplay() Exception:" + e);
            Log.d(TAG, "requestToDisplay()" + content);
        }
    }

    /**
     * Viewのクリアを要求します。
     */
    private void clear() {
        try {
//            view.clear();
        } catch (final Exception e) {
            Log.d(TAG, "clear() Exception:" + e);
        }
    }
}
